package com.gwtintegration.smartrf.server.entity.locator;

import java.lang.reflect.ParameterizedType;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.log4j.Logger;

import com.google.web.bindery.requestfactory.shared.Locator;
import com.gwtintegration.smartrf.server.entity.Identifiable;
import com.gwtintegration.smartrf.server.entity.Versionable;

public class JpaEntityLocator<T extends Identifiable<I>, I> extends Locator<T, I> {

	private static final Logger logger = Logger.getLogger(JpaEntityLocator.class);

	@PersistenceContext
	private EntityManager entityManager;

	private Class<T> entityClass;

	private Class<I> entityIdClass;

	@SuppressWarnings("unchecked")
	public JpaEntityLocator() {
		ParameterizedType genericSuperclass = (ParameterizedType) getClass().getGenericSuperclass();
		this.entityClass = (Class<T>) genericSuperclass.getActualTypeArguments()[0];
		this.entityIdClass = (Class<I>) genericSuperclass.getActualTypeArguments()[1];
	}

	@Override
	public T create(Class<? extends T> clazz) {
		try {
			return clazz.newInstance();
		} catch (Exception e) {
			logger.error("Can't create a new instance of " + clazz.getName() + ".", e);
		}

		return null;
	}

	@Override
	public T find(Class<? extends T> clazz, I id) {
		return entityManager.find(clazz, id);
	}

	@Override
	public Class<T> getDomainType() {
		return entityClass;
	}

	@Override
	public I getId(T domainObject) {
		return domainObject.getId();
	}

	@Override
	public Class<I> getIdType() {
		return entityIdClass;
	}

	@Override
	public Object getVersion(T domainObject) {

		if (domainObject instanceof Versionable) {
			return ((Versionable) domainObject).getVersion();
		}

		return null;
	}
}
